import os
import sys
from enum import unique, Enum
from functools import partial
from random import uniform
from typing import Optional

from PyQt5.QtCore import QSize, pyqtSignal
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QApplication


@unique
class TitlePanelBtnType(Enum):
    TPB_MIN = 1
    TPB_HIDE = 2
    TPB_RESTORE = 3


class TitlePanelWidget(QWidget):
    __Id = 0
    __vLayout = None
    __customBottomWidget = []
    __panelIconMin = None
    __panelIconClose = None
    __panelIconRestore = None
    btnEvent = pyqtSignal(int, TitlePanelBtnType)
    __autoFillBackGroundColor = False
    __captionHeight = 30

    def __init__(self, uniqueId: int, parent: Optional[QWidget] = None):
        super().__init__(parent)
        self.__customBottomWidget = []
        self.__Id = uniqueId
        self.__initUi()
        if self.__autoFillBackGroundColor:
            self.setStyleSheet(f'background-color: rgb({uniform(0, 255)}, {uniform(0, 255)}, {uniform(0, 255)});')

    def __initUi(self):
        vLayout = QVBoxLayout()
        widget = self.__createCaptionWidget()
        vLayout.addWidget(widget)
        vLayout.setSpacing(0)
        vLayout.setContentsMargins(0, 0, 0, 0)
        self.__vLayout = vLayout
        self.setLayout(vLayout)

    def __createCaptionWidget(self):
        widget = QWidget()
        widget.setObjectName('VBoxCaption')
        widget.setFixedHeight(self.__captionHeight)
        if self.__autoFillBackGroundColor:
            widget.setStyleSheet(f'.QWidget{{border: 1px solid rgb({uniform(0, 255)}, {uniform(0, 255)}, {uniform(0, 255)});}}')
        hLayout = QHBoxLayout()
        ctrlTitle = QLabel('', self)
        ctrlTitle.setObjectName('VBoxTitle')
        restoreBtn = QPushButton()
        restoreBtn.setMaximumWidth(self.__captionHeight-2)
        if self.__panelIconRestore is None:
            restoreBtn.setText('+')
        else:
            restoreBtn.setIconSize(QSize(10, 10))
            restoreBtn.setIcon(self.__panelIconRestore)
        restoreBtn.setObjectName('VBoxBtnRestore')
        restoreBtn.setToolTip('展开')
        restoreBtn.hide()
        minBtn = QPushButton()
        minBtn.setMaximumWidth(self.__captionHeight-2)
        if self.__panelIconMin is None:
            minBtn.setText('-')
        else:
            minBtn.setIconSize(QSize(10, 10))
            minBtn.setIcon(self.__panelIconMin)
        minBtn.setObjectName('VBoxBtnMin')
        minBtn.setToolTip('收缩')
        closeBtn = QPushButton()
        closeBtn.setMaximumWidth(self.__captionHeight-2)
        if self.__panelIconClose is None:
            closeBtn.setText('X')
        else:
            closeBtn.setIconSize(QSize(10, 10))
            closeBtn.setIcon(self.__panelIconClose)
        closeBtn.setObjectName('VBoxBtnClose')
        closeBtn.setToolTip('隐藏')
        hLayout.addWidget(ctrlTitle)
        hLayout.addWidget(restoreBtn)
        hLayout.addWidget(minBtn)
        hLayout.addWidget(closeBtn)
        hLayout.setContentsMargins(0, 0, 0, 0)
        widget.setLayout(hLayout)
        restoreBtn.clicked.connect(partial(self.__clickBtn, TitlePanelBtnType.TPB_RESTORE))
        minBtn.clicked.connect(partial(self.__clickBtn, TitlePanelBtnType.TPB_MIN))
        closeBtn.clicked.connect(partial(self.__clickBtn, TitlePanelBtnType.TPB_HIDE))
        self.__title = ctrlTitle
        self.__minBtn = minBtn
        self.__restoreBtn = restoreBtn
        self.__closeBtn = closeBtn
        return widget

    def __clickBtn(self, type: TitlePanelBtnType):
        if type == TitlePanelBtnType.TPB_MIN:
            self.__minBtn.hide()
            self.__restoreBtn.show()
            for w in self.__customBottomWidget:
                w.setVisible(False)
        if type == TitlePanelBtnType.TPB_RESTORE:
            self.__restoreBtn.hide()
            self.__minBtn.show()
            for w in self.__customBottomWidget:
                w.setVisible(True)
        elif type == TitlePanelBtnType.TPB_HIDE:
            self.hide()
        else:
            pass
        self.btnEvent.emit(self.__Id, type)

    def SetTitle(self, title: str):
        self.__title.setText(title)

    def GetTitle(self):
        return self.__title.text()

    def SetCustomWidget(self, widget: QWidget):
        self.__vLayout.addWidget(widget)
        self.__customBottomWidget.append(widget)

    def IsMin(self):
        return not self.__customBottomWidget[0].isVisible()

    def Restore(self):
        self.__clickBtn(TitlePanelBtnType.TPB_RESTORE)

    def Hide(self):
        self.__clickBtn(TitlePanelBtnType.TPB_HIDE)

    def SetIcons(self, min: Optional[QIcon], restore: Optional[QIcon], close: Optional[QIcon]):
        if min is not None:
            self.__minBtn.setText('')
            self.__minBtn.setIconSize(QSize(10, 10))
            self.__minBtn.setIcon(min)
            self.__panelIconMin = min
        if restore is not None:
            self.__restoreBtn.setText('')
            self.__restoreBtn.setIconSize(QSize(10, 10))
            self.__restoreBtn.setIcon(restore)
            self.__panelIconRestore = restore
        if close is not None:
            self.__closeBtn.setText('')
            self.__closeBtn.setIconSize(QSize(10, 10))
            self.__closeBtn.setIcon(close)
            self.__panelIconClose = close


class PanelsGroupWidget(QWidget):
    __panelsNum = 0
    __panels = []
    panelHideEvent = pyqtSignal(str)

    def __init__(self, panelsNum: int, parent: Optional[QWidget] = None):
        super().__init__(parent)
        self.__panelsNum = panelsNum
        self._initUi()

    def _initUi(self):
        vLayout = QVBoxLayout()
        for i in range(self.__panelsNum):
            panel = self.__createPanel(i+1)
            self.__panels.append(panel)
            vLayout.addWidget(panel)
        vLayout.setContentsMargins(1, 0, 1, 0)
        vLayout.setSpacing(0)
        self.setLayout(vLayout)

    def __createPanel(self, _id: int):
        panel = TitlePanelWidget(_id, self)
        panel.setObjectName('PanelVBox')
        panel.btnEvent.connect(self.__onPanelBtnClicked)
        return panel

    def __onPanelBtnClicked(self, _id: int, type: TitlePanelBtnType):
        # print(f'{_id=}, {type}')
        # print(f'{self.__panels[_id-1].height()=}')
        if type == TitlePanelBtnType.TPB_MIN:
            minPanelNum = 0
            for i in range(self.__panelsNum):
                if _id-1 != i:
                    w = self.__panels[i]
                    if w.IsMin():
                        # print(f'panel:{i} {id(w)=} is min')
                        minPanelNum += 1
            if minPanelNum+1 == self.__panelsNum:
                restoreIdex = (_id + 1)%self.__panelsNum
                print(f'auto restore panel:{restoreIdex}')
                self.__panels[restoreIdex].Restore()
        elif type == TitlePanelBtnType.TPB_HIDE:
            self.panelHideEvent.emit(self.__panels[_id-1].GetTitle())
            hidePanelNum = 0
            for i in range(self.__panelsNum):
                if _id - 1 != i:
                    w = self.__panels[i]
                    if not w.isVisible():
                        # print(f'panel:{i} {id(w)=} is hide')
                        hidePanelNum += 1
            if hidePanelNum + 1 == self.__panelsNum:
                # 所有的面板都隐藏，则自动隐藏自身
                self.setVisible(False)
        #self.layout().activate()

    def SetTitle(self, index: int, title: str):
        if index >= self.__panelsNum:
            return
        self.__panels[index].SetTitle(title)

    def SetCustomWidget(self, index: int, widget: QWidget):
        if index >= self.__panelsNum:
            return
        self.__panels[index].SetCustomWidget(widget)

    def HideWidget(self, index: int, bHide: bool = False):
        if index >= self.__panelsNum:
            return
        if bHide:
            self.__panels[index].Hide()
        else:
            self.setVisible(True)
            self.__panels[index].showNormal()
            self.__panels[index].Restore()

    def resizeEvent(self, event):
        super().resizeEvent(event)
        # self.updateGeometry()
        # print(f'resizeEvent, {self.width()} x {self.height()}')

    def SetPanelMinHeight(self, index: int, height: int):
        w = self.__panels[index]
        w.setMinimumHeight(height)

    def SetPanelMaxHeight(self, index: int, height: int):
        w = self.__panels[index]
        w.setMaximumHeight(height)

    def SetPanelFixHeight(self, index: int, height: int):
        w = self.__panels[index]
        w.setFixedHeight(height)

    def SetPanelStretch(self, index: int, strech):
        self.layout().setStretch(index, strech)

    def SetIcons(self, min: Optional[QIcon], restore: Optional[QIcon], close: Optional[QIcon]):
        for i in range(self.__panelsNum):
            self.__panels[i].SetIcons(min, restore, close)



if __name__ == "__main__":
    app = QApplication(sys.argv)
    try:
        current_path = os.path.abspath(__file__)
        path = os.path.dirname(current_path)
        path = os.path.dirname(path)
        #app.setStyleSheet(open(f'{path}/styleSheet.qss', encoding='utf-8').read())
        window = PanelsGroupWidget(3)
        window.setMinimumWidth(200)
        window.setMinimumHeight(400)
        window.setFixedSize(300, 500)
        for i in range(3):
            window.SetTitle(i, f'标题{i}')
            p = QWidget()
            lay = QVBoxLayout()
            label = QLabel(f'测试{i}')
            btn = QPushButton(f'按钮{i}')
            lay.addWidget(label)
            lay.addWidget(btn)
            p.setLayout(lay)
            #p.setMaximumHeight(100+50*i)
            p.setStyleSheet(f'background-color: rgb({i*50+10}, {i*50+10}, {i*50+10});')
            window.SetCustomWidget(i, p)

        window.showNormal()
        sys.exit(app.exec_())

    except Exception as e:
        print(e)




